function SDX_GroupBy(_RootObject)
{
 this.RootObject = _RootObject ;
 this.Rows = new Array();
 this.AllRows = new Array();
 this.Row = Row;
 this.InsertGroupByRow = InsertGroupByRow;
 this.SelectedGroupBy = null;
 this.Columns = new Array();
 this.InsertColumn = InsertColumn;
 this.IsGroupByColumn=IsGroupByColumn;
 this.Initialize = Initialize;
 this.HTMLOutPut = "";
 //this.FindParentGroupByRow = FindParentGroupByRow;
 //this.CreateGroupByRowForNewRow = CreateGroupByRowForNewRow;
 this.FillGroupByChildsAndRows = FillGroupByChildsAndRows ;
 function InsertGroupByRow( _HeaderValue, _HeaderText, _Column, _CellValue, _Level)
 {
  this.Rows[this.Rows.length]=new Row(this.RootObject, this.AllRows.length, null, _HeaderValue, _HeaderText, _Column, _CellValue, _Level)
  this.AllRows[this.AllRows.length]=this.Rows[this.Rows.length-1]
  return this.Rows[this.Rows.length-1]
 }
 // START GROUPBYROW
 function Row(_RootObject, _ID, _ParentRow, _HeaderValue, _HeaderText, _Column, _CellValue, _Level)
 {
  this.RootObject = _RootObject ;
  this.ID = _ID
  this.HMTLTrID=(_ParentRow!=null?_ParentRow.HMTLTrID + "_" + this.ID:"SDXGroupByRow_TR_" + this.RootObject.Name + "_" + this.ID)
  this.HTMLTblID=(_ParentRow!=null?_ParentRow.HTMLTblID + "_" + this.ID:"SDXGroupByRow_Tbl_" + this.RootObject.Name + "_" + this.ID)
  this.HTMLGroupByImageID = "SDXRowIMG_" + this.HTMLTblID ;
  this.Initialize=false;
  this.GetEvalObjectString = GetEvalObjectString ;
  this.DeActivate = DeActivate;
  this.Activate = Activate;
  this.HeaderText = _HeaderText;
  this.HeaderValue = _HeaderValue;
  this.CellValue = _CellValue ;
  this.ParentRow = _ParentRow;
  this.DataTable = null;
  this.ChildGroupByRows = new Array();
  this.InsertGroupByRow = InsertGroupByRow;
  this.GroupColumn = _Column;
  this.InsertChildDataRow = InsertChildDataRow;
  this.ChildDataRows = new Array();
  this.Level = _Level;
  this.SetVisible = SetVisible;
  this.CreateGroupByGroupTable = CreateGroupByGroupTable ;
  this.CreateGroupByDataTable = CreateGroupByDataTable ;
  this.InsertAfter = InsertAfter
  this.HTMLOutPut = HTMLOutPut
  function GetEvalObjectString()
  {
   return this.RootObject.Name + ".GroupBy.AllRows[" + this.ID + "]"
  }
  function DeActivate()
  {
   if(document.getElementById(this.HTMLTblID))
   {
    document.getElementById(this.HTMLTblID).childNodes[0].childNodes[0].childNodes[0].style.backgroundColor=''
    document.getElementById(this.HTMLTblID).childNodes[0].childNodes[0].childNodes[1].style.backgroundColor=''
    document.getElementById(this.HTMLTblID).childNodes[0].childNodes[1].childNodes[0].style.backgroundColor=''
   }
  }
  function Activate()
  {
   if(this.RootObject.GroupBy.SelectedGroupBy!=null && this.RootObject.GroupBy.SelectedGroupBy!=this)
    this.RootObject.GroupBy.SelectedGroupBy.DeActivate()
   document.getElementById(this.HTMLTblID).childNodes[0].childNodes[0].childNodes[0].style.backgroundColor='gray'
   document.getElementById(this.HTMLTblID).childNodes[0].childNodes[0].childNodes[1].style.backgroundColor='gray'
   document.getElementById(this.HTMLTblID).childNodes[0].childNodes[1].childNodes[0].style.backgroundColor='gray'
   this.RootObject.GroupBy.SelectedGroupBy=this;
  }
  function HTMLOutPut()
  {
  }
  function InsertAfter(newElement,targetElement)
  {	//target is what you want it to go after. Look for this elements parent.
   	var parent = targetElement.parentNode;
   	//if the parents lastchild is the targetElement...
   	if(parent.lastchild == targetElement) {		//add the newElement after the target element.
   			parent.appendChild(newElement);		
   	} else {		// else the target has siblings, insert the new element between the target and it's next sibling.
   			parent.insertBefore(newElement, targetElement.nextSibling);	
   	}
  }
  function CreateGroupByGroupTable(TRID, _GroupByRow)
  {
    this.RootObject.GroupBy.FillGroupByChildsAndRows(_GroupByRow.ChildDataRows, _GroupByRow)
    var currentRow = document.getElementById(TRID) ;
//    var currentTable = currentRow.parentNode.parentNode ;
    for(var nY in _GroupByRow.ChildGroupByRows)
    {
      groupByRow = _GroupByRow.ChildGroupByRows[nY] ; 
      var groupByRowTR = document.createElement("tr") ;
      groupByRowTR.setAttribute("id", groupByRow.HMTLTrID) ;
      groupByRowTR.setAttribute("style", "display:block") ;
      groupByRowTR.setAttribute("object", groupByRow.GetEvalObjectString()) ;
      for(var i=0;i<_GroupByRow.Level;i++)
      {
          var groupByRowTDLeftSpace = document.createElement("td") ;
          groupByRowTDLeftSpace.setAttribute("style", "border-collapse: collapse") ;
          groupByRowTDLeftSpace.setAttribute("onmouseover", "this.style.cursor='" + (navigator.appName=="Microsoft Internet Explorer"?"hand":"pointer") + "'" ) ;
          groupByRowTDLeftSpace.innerHTML = "&nbsp;&nbsp;&nbsp;" ;
          groupByRowTR.appendChild(groupByRowTDLeftSpace) ;
      }

      var groupByRowTD1 = document.createElement("td") ;
      groupByRowTD1.setAttribute("align", "left") ;
      groupByRowTD1.setAttribute("colspan", (this.RootObject.Columns.Columns.length + this.RootObject.GroupBy.Columns.length-_GroupByRow.Level) ) ;
      groupByRowTD1.setAttribute("onmouseover", "this.style.cursor='" + (navigator.appName=="Microsoft Internet Explorer"?"hand":"pointer") + "'" ) ;
      var onclickString = groupByRow.GetEvalObjectString() + ".SetVisible('" + groupByRow.HMTLTrID + "',this,'" + groupByRow.HTMLGroupByImageID + "')" ;
      groupByRowTD1.innerHTML = "<a onclick=\"" + onclickString + "\" href='#'><img border=0 id='" + groupByRow.HTMLGroupByImageID + "' height=15 width=15 src=\"" + this.RootObject.ResourcePath + "images/plus.gif\"></a>&nbsp;" +
                                           groupByRow.HeaderText + " (" + groupByRow.ChildDataRows.length + ")" ;
      groupByRowTR.appendChild(groupByRowTD1) ;

      this.InsertAfter(groupByRowTR,currentRow);
      groupByRowTD1.colSpan = (this.RootObject.Columns.Columns.length + this.RootObject.GroupBy.Columns.length-_GroupByRow.Level);
    }
  }
  function CreateGroupByDataTable(TRID, _GroupByRow)
  {
   currentRow = document.getElementById(this.HMTLTrID) ;
   var currentTable = currentRow.parentNode.parentNode ;
   var dt=this.RootObject.Tables.InsertTable(_GroupByRow.ChildDataRows,_GroupByRow)
   for(var i in dt.Rows)
   {
     dt.Rows[i].DataTable = dt;
     document.getElementById(this.RootObject.DummyDivHTMLID).innerHTML = "<table>" + dt.Rows[i].GetRowView().HTMLOutPut() + "</table>" ;
     this.InsertAfter(document.getElementById(this.RootObject.DummyDivHTMLID).childNodes[0].childNodes[0].childNodes[0],currentRow);
   }
  }

  function SetVisible(TRID,objTD,imgID)
  {
   if(this.Initialize == false)
   {
     if(this.Level < this.RootObject.GroupBy.Columns.length)
     {
      this.CreateGroupByGroupTable(TRID, this);
     }
     else
     {
      this.CreateGroupByDataTable(TRID, this);
     }
     this.Initialize = true ;
   }
   var isCloseAction = false;
   if(objTD.innerHTML.indexOf("minus.gif")>0)
    isCloseAction = true
   document.getElementById(imgID).src=(document.getElementById(imgID).src.indexOf("plus.gif")>0?this.RootObject.ResourcePath + "images/minus.gif":this.RootObject.ResourcePath + "images/plus.gif")
   currentRow = document.getElementById(TRID).nextSibling ;
   var isLastGroupByRow = (currentRow.id.indexOf("SDXGroupByRow_TR_")>-1?false:true)
   while(currentRow != null)
   {
    var isDataRow = (currentRow.id.indexOf("SDXGroupByRow_TR_")>-1?false:true) ;
    if(currentRow.id.indexOf(TRID)<0 && isDataRow == false)
     return ;
    if(isDataRow == true)
    {
     if(isLastGroupByRow == true)
     {
      currentRow.style.display = (isCloseAction==true?'none':'block') ;
     }
     else if(isCloseAction ==true)
     {
      currentRow.style.display = 'none' ;
     }
    }
    else
    {
     currentRow.style.display = (isCloseAction==true?'none':'block') ;
    }
    currentRow = currentRow.nextSibling
   }
  }
  function InsertGroupByRow(_HeaderValue, _HeaderText, _Column, _CellValue)
  {
   this.ChildGroupByRows[this.ChildGroupByRows.length] = new this.RootObject.GroupBy.Row(this.RootObject,this.RootObject.GroupBy.AllRows.length, this, _HeaderValue, _HeaderText, _Column, _CellValue, this.Level+1)
   this.RootObject.GroupBy.AllRows[this.RootObject.GroupBy.AllRows.length] = this.ChildGroupByRows[this.ChildGroupByRows.length-1]
   return this.ChildGroupByRows[this.ChildGroupByRows.length-1] ;
  }
  function InsertChildDataRow(objRow)
  {
   this.ChildDataRows[this.ChildDataRows.length]=objRow;
  }
 }
 // END GROUPBYROW

 function InsertColumn(_ColumnKey)
 {
  for(var nX in this.RootObject.Columns.Columns)
  {
   if(this.RootObject.Columns.Columns[nX].Key == _ColumnKey)
   {
    if(this.IsGroupByColumn(this.RootObject.Columns.Columns[nX].ID) == true)
        return false;
    this.Columns[this.Columns.length]=this.RootObject.Columns.Columns[nX].ID;
    return true;
   }
  }
  return false;
 }
 function IsGroupByColumn(_ColumnID)
 {
  for(var nX in this.Columns)
  {
   if(this.Columns[nX] == _ColumnID)
    return true;
  }
  return false;
 }

 function Initialize()
 {
  // If there is no groupby row exists
  if(this.Columns.length<1)
  {
   var aRows=new Array()
   for(var nX in this.RootObject.Rows.Rows)
   {
    aRows[aRows.length]=this.RootObject.Rows.Rows[nX] ;
   }
   var dt=this.RootObject.Tables.InsertTable(aRows,null)
   this.HTMLOutPut=dt.HTMLOutPut()
   return;
  }

  this.HTMLOutPut="<table width=100% id=\"SDXGrid_" + this.RootObject.Name + "\" " + this.RootObject.Styles.GetStyleHTML(this.RootObject.Styles.Style) + " ><tr>" +
                  this.RootObject.Columns.GetHTMLOutPuts() + "</tr>" ;
  this.FillGroupByChildsAndRows( this.RootObject.Rows.Rows);
  for(var nY in this.Rows)
  {
      _GroupByRow = this.Rows[nY];
      this.HTMLOutPut+="<tr id='" + _GroupByRow.HMTLTrID + "' style='display:block' object='" + _GroupByRow.GetEvalObjectString() + "' " + this.RootObject.Styles.GetStyleHTML(this.RootObject.Styles.GroupByItemStyle) + " >" +
                                          "<td align='left' colspan=" + (this.RootObject.Columns.Columns.length + this.RootObject.GroupBy.Columns.length) + " onmouseover=\"this.style.cursor='" + (navigator.appName=="Microsoft Internet Explorer"?"hand":"pointer") + "'\" align=center onclick=\"" + _GroupByRow.GetEvalObjectString() + ".SetVisible('" + _GroupByRow.HMTLTrID + "',this,'" + _GroupByRow.HTMLGroupByImageID + "')\"><img id='" + _GroupByRow.HTMLGroupByImageID + "' height=15 width=15 src=\"" + this.RootObject.ResourcePath + "images/plus.gif\">&nbsp;" +
                                           _GroupByRow.HeaderText + " (" + _GroupByRow.ChildDataRows.length + ")</td></tr>"
  }
  }
  function FillGroupByChildsAndRows(_ChildDataRows, _GroupByRow)
  {
   if(_GroupByRow == null)
   {
       this.Rows=new Array();
   }
   else
   {
       _GroupByRow.ChildGroupByRows = new Array()
   }
   var nColumnNo ;
   var groupByRows ;
   var bHasGroup=false;
   for(var nX in _ChildDataRows)
   {
    bHasGroup=false;
    if(_GroupByRow==null)
    {
        nColumnNo= this.Columns[0] ;
        groupByRows = this.Rows ;
    }
    else
    {
        nColumnNo= this.Columns[_GroupByRow.Level];
        groupByRows = _GroupByRow.ChildGroupByRows ;
    }
    if(this.RootObject.Datas.GetDataByKeyID("Current",_ChildDataRows[nX].DataKeyID) == null)
        continue;
    var data = _ChildDataRows[nX].GetRowView().Cells.GetCell(this.RootObject.Columns.Columns[nColumnNo].Key).HTMLOutPut().toString() ;
    var cellValue = _ChildDataRows[nX].GetRowView().Cells.GetCell(this.RootObject.Columns.Columns[nColumnNo].Key).Value ;
    for(var nY in groupByRows)
    {
     if(groupByRows[nY].HeaderValue==data)
     {
      bHasGroup=true;
      groupByRows[nY].InsertChildDataRow(_ChildDataRows[nX])
      break;
     }
    }
    if( bHasGroup == false )
    {
     var groupRow;
     if(_GroupByRow == null)
     {
         groupRow = this.InsertGroupByRow(data,data,this.RootObject.Columns.Columns[nColumnNo],cellValue,(_GroupByRow==null?1:_GroupByRow.Level+1))
     }
     else
     {
         groupRow = _GroupByRow.InsertGroupByRow(data,data,this.RootObject.Columns.Columns[nColumnNo],cellValue,(_GroupByRow==null?1:_GroupByRow.Level+1))
     }
     groupRow.InsertChildDataRow(_ChildDataRows[nX])
    }
   }
  } 
}